package com.tree.thread.pubsub;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @ClassName com.tree.thread.pubsub
 * Description: <类功能描述>. <br>
 * <p>
 * <使用说明>
 * </p>
 * @Author tree
 * @Date 4/13/24 6:03 PM
 * @Version 1.0
 */
public class AqsProduceConsumerTest {
    static volatile List<Integer> container = new ArrayList<>();

    public static void main(String[] args) {

        Lock lock = new ReentrantLock();
        Condition produceCondition = lock.newCondition();
        Condition consumerCondition = lock.newCondition();
        Thread producer = new Thread(
                new AQSProducer(container,lock,produceCondition,consumerCondition),"Produce");
        Thread consumer = new Thread(
                new AQSConsumer(container,lock,produceCondition,consumerCondition),"Consumer");

        producer.start();
        consumer.start();

    }
}


class AQSProducer implements Runnable{
    /**
     * 容器
     */
    private List<Integer> container ;
    private Lock lock;

    /**
     * 生产者条件
     */
    private Condition producerCondition;
    /**
     * 消费者条件
     */
    private Condition consumerCondition;

    /**
     * 容器大小
     */
    private static int CAPACITY  =10;

    public AQSProducer(List<Integer> container, Lock lock,
                       Condition producerCondition, Condition consumerCondition){
        this.container = container;
        this.lock = lock;
        this.producerCondition = producerCondition;
        this.consumerCondition =consumerCondition;
    }

    public void produce(){
//        System.out.println(container.size());

        lock.lock();
        try {
            if(container.size() == CAPACITY){
                System.out.println("【"+Thread.currentThread()+"】生产的空间满了， 等待被消费...."+", size = "+container.size());
                producerCondition.await();
            }
            Random random = new Random();
            int tmp = random.nextInt(10);
            container.add(tmp);
            System.out.println("【"+Thread.currentThread()+"】生产产品："+tmp+", size = "+container.size());
            consumerCondition.signal();


        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }
    @Override
    public void run() {
        while (true){
            produce();
            //每隔1s生产1个
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}

class AQSConsumer implements Runnable{
    /**
     * 容器
     */
    private List<Integer> container ;
    private Lock lock;

    /**
     * 生产者条件
     */
    private Condition producerCondition;
    /**
     * 消费者条件
     */
    private Condition consumerCondition;


    public AQSConsumer(List<Integer> container, Lock lock,
                       Condition producerCondition, Condition consumerCondition){
        this.container = container;
        this.lock = lock;
        this.producerCondition = producerCondition;
        this.consumerCondition =consumerCondition;
    }

    public void consumer(){
        System.out.println("enter consumer , size = " +container.size());

        lock.lock();
        try {
            if(container.size() == 0){
                System.out.println("【"+Thread.currentThread()+"】空间没有多余的了， 等待生产者重新放入...."+", size = "+container.size());
                consumerCondition.await();
            }
            System.out.println("【"+Thread.currentThread()+"】消费前size = "+container.size());
            int tmp = container.remove(0);

            System.out.println("【"+Thread.currentThread()+"】消费产品："+tmp+", 消费后size = "+container.size());
            producerCondition.signal();


        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }
    @Override
    public void run() {
        while (true){
            consumer();
            //每隔1s消费1个
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

    }
}